非阻塞式socket建立以及如何判断对方断开

您所在的位置:网站首页 socket c语言 服务端 判断客户端断开 非阻塞式socket建立以及如何判断对方断开

非阻塞式socket建立以及如何判断对方断开

2024-07-11 20:15| 来源: 网络整理| 查看: 265

  最近写的程序要求的是在控制线程中使用非阻塞的socket,以前没怎么接触过,先贴出代码如下:

#define sockopt_noblock(socket, noblock) do{\     int val = (noblock);\     ioctl((socket), FIONBIO, (int)&val);\ } while(0)

int conn_nonb(int sockfd, const struct sockaddr_in *saptr, socklen_t salen, int nsec) {     int flags, n, error, code;     socklen_t len;     fd_set wset;     struct timeval tval;     flags = fcntl(sockfd, F_GETFL, 0);     fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);     sockopt_noblock(sockfd, 1);     error = 0;     if ((n == connect(sockfd, (struct sockaddr *)saptr, salen)) == 0) {         goto done;     } else if (n < 0 && errno != EINPROGRESS){         return RS_ERROR;     }     /* Do whatever we want while the connect is taking place */     FD_ZERO(&wset);     FD_SET(sockfd, &wset);     tval.tv_sec = nsec;     tval.tv_usec = 0;     if ((n = select(sockfd+1, NULL, &wset,                     NULL, nsec ? &tval : NULL)) == 0) {         close(sockfd);  /* timeout */         errno = ETIMEDOUT;         return RS_ERROR1;     }     if (FD_ISSET(sockfd, &wset)) {         len = sizeof(error);         code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);         /* 如果发生错误,Solaris实现的getsockopt返回-1,          * 把pending error设置给errno. Berkeley实现的          * getsockopt返回0, pending error返回给error.          * 我们需要处理这两种情况 */         if (code < 0 || error) {             close(sockfd);             if (error)                 errno = error;             return RS_ERROR;         }     } else {         fprintf(stderr, "select error: sockfd not set");         exit(0);     } done:     //fcntl(sockfd, F_SETFL, flags);  /* restore file status flags ,这里看你自身的情况,可以选择恢复或者不恢复 */     return RS_OK;        /* return 0 */ }

注:此代码是别人写的,可以拿来直接用,但是在这里连接只能保证你connect的时候是成功的,但是不能保证你后续read、write、send、recv是成功的。因此你需要在每次 read和write前检查连接是否断开。可以通过以下办法来判断(也是网上查找的资料,自己用过,是这样的):

在阻塞模式下,

recv和read 一般返回0,断开。(这个待议,我没试过)

非阻塞模式下, 错误代码是EAGAIN/EWOULDBLOCK时,表示正常,未读写数据。 recv()或read()返回0时,表示断开,返回-1而errno不是EAGAIN/EWOULDBLOCK时,表示有其他错误,一般建议断开。

这里有其他的判断方法,其实和我上面说的一致。

正常断开连接情况下,判断非阻塞模式socket连接是否断开

摘自:http://blog.chinaunix.net/uid-15014334-id-3429627.html

在UNIX/LINUX下,

1,对于主动关闭的SOCKET, recv返回-1,而且errno被置为9(#define EBADF   9 /* Bad file number */)或104 (#define ECONNRESET 104 /* Connection reset by peer */)

2,对于被动关闭的SOCKET,recv返回0,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)

3,对正常的SOCKET, 如果有接收数据,则返回>0, 否则返回-1,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)

 

因此对于简单的状态判断(不过多考虑异常情况),     recv返回>0, 正常     返回-1,而且errno被置为11  正常     其它情况    关闭



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3